#!/usr/bin/env python
#
# Copyright 2008 Jake
#
import os
import logging
import cgi
import datetime
import wsgiref.handlers

from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.api import memcache

class CacheManager:
    def __init__(self):
        self.client = memcache.Client()
        
    def getHash(self,user,curPage,limit):
        u = ""
        if user:
            u = user.user_id()
        return "user=%s&limit=%d&page=%d" % (u,limit,curPage)
        
    def get(self,user,curPage,limit):
        h = self.getHash(user,curPage,limit)
        return self.client.get(h)
    
    def set(self,user,curPage,limit,data):
        h = self.getHash(user,curPage,limit)
        return self.client.set(h,data)
    
    def clear(self):
        return self.client.flush_all()
        

class Paginator():
    def __init__(self,all,curPage,limit):
        self.item_count = all
        self.page_cur = curPage
        self.page_limit = limit
        self.page_min = 1
        m = all%limit
        self.page_max = all/limit
        if m>0:
            self.page_max += 1
        if self.page_cur>self.page_max: self.page_cur = self.page_max
        if self.page_cur<self.page_min: self.page_cur = self.page_min
        self.page_prev = self.page_cur-1
        if self.page_prev<self.page_min: self.page_prev = self.page_min
        self.page_next = self.page_cur+1
        if self.page_next>self.page_max: self.page_next = self.page_max
        self.page_list = range(self.page_min,self.page_max+1)

    def getLimit(self):
        return self.page_limit

    def getPos(self):
        return (self.page_cur-1)*self.page_limit


class Posts(db.Model):
    author = db.UserProperty()
    body = db.TextProperty()
    created = db.DateTimeProperty(auto_now_add=True)


class MainPage(webapp.RequestHandler):
    def get(self,limit=5,curPage=1):
        query = Posts.all()
        query.order("-created")
        try:
            limit = int(limit)
            curPage = int(curPage)
        except ValueError:
            limit = 5
            curPage = 1
        user = users.get_current_user()
        cache = CacheManager()
        cdata = cache.get(user,curPage,limit)
        if cdata:
            self.response.out.write(cdata)
            return
        pager = Paginator(query.count(),curPage,limit)
        posts = query.fetch(pager.getLimit(),pager.getPos())
        # user
        if user:
            _user = {
                'nickname':user.nickname(),
                'email':user.email(),
            }
            url = users.create_logout_url("/")
        else:
            _user = {}
            url = users.create_login_url("/")

        template_values = {
            'posts': posts,
            'user': _user,
            'url': url,
            'pager': pager,
        }

        if posts is None:
            self.redirect('/notfound')
        else:
            path = os.path.join(os.path.dirname(__file__), "index.html")
            outdata = template.render(path, template_values)
            self.response.out.write(outdata)
            cache.set(user,curPage,limit,outdata)


class addPost(webapp.RequestHandler):
    def post(self):
        p = Posts()
        if users.get_current_user():
            p.author = users.get_current_user()
        p.body = self.request.get('txt')
        if len(p.body) > 1:
            p.put()
            CacheManager().clear()
            logging.info('add post %s' % (id))
        self.redirect('/')

class addPostByAjax(webapp.RequestHandler):
    def post(self):
        p = Posts()
        if users.get_current_user():
            p.author = users.get_current_user()
        p.body = self.request.get('txt')
        if len(p.body.strip()) > 1:
            p.put()
            logging.info('add post %s' % (id))
            template_values = {
                'post': p,
                'user': p.author,
            }
            path = os.path.join(os.path.dirname(__file__), "post.html")
            self.response.out.write(template.render(path, template_values))
            CacheManager().clear()

class editPost(webapp.RequestHandler):
    def get(self,id):
        if not users.is_current_user_admin():
            self.redirect('/notallow')
        else:
            post = Posts.get_by_id(int(id))
            if post is None:
                self.redirect('/notfound')
            else:
                user = users.get_current_user()
                if user:
                    _user = {
                        'nickname':user.nickname(),
                        'email':user.email(),
                    }
                    url = users.create_logout_url("/")
                else:
                    _user = {}
                    url = users.create_login_url("/")
    
                template_values = {
                    'post': post,
                    'user': _user,
                    'url': url,
                }
                path = os.path.join(os.path.dirname(__file__), "edit.html")
                self.response.out.write(template.render(path, template_values))

class savePost(webapp.RequestHandler):
    def post(self,id):
        if users.is_current_user_admin():
            post = Posts.get_by_id(int(id))
            if post is None:
                self.redirect('/notfound')
            if users.get_current_user():
                post.author = users.get_current_user()
            post.body = self.request.get('txt',post.body)
            if len(post.body) > 1:
                post.put()
                logging.info('save post %s' % (id))
            self.redirect("/")
            CacheManager().clear()
        else:
            self.redirect('/notallow')

class delPost(webapp.RequestHandler):
    def get(self,id):
        if users.is_current_user_admin():
            post = Posts.get_by_id(int(id))
            if post is None:
                self.redirect('/notfound')
            post.delete()
            logging.info('delete post %s' % (id))
            self.redirect('/')
            CacheManager().clear()
        else:
            self.redirect('/notallow')

class showTXT(webapp.RequestHandler):
    def get(self,id):
        post = Posts.get_by_id(int(id))
        if post is None:
            self.redirect('/notfound')
        else:
            self.response.headers["Content-Type"] = "text/plain; charset=utf-8"
            self.response.out.write(post.body)

class showHTML(webapp.RequestHandler):
    def get(self,id):
        post = Posts.get_by_id(int(id))
        if post is None:
            self.redirect('/notfound')
        else:
            self.response.out.write(post.body)

application = webapp.WSGIApplication([
    ('/', MainPage),
    ('/limit/(\d+)/page/(\d+)', MainPage),
    ('/(\d+)\.txt', showTXT),
    ('/(\d+)\.html', showHTML),
    ('/del/(\d+)', delPost),
    ('/edit/(\d+)', editPost),
    ('/save/(\d+)', savePost),
    ('/add', addPost),
    ('/ajax_add', addPostByAjax)
], debug=False)


def main():
    wsgiref.handlers.CGIHandler().run(application)


if __name__ == '__main__':
    main()
